"""
1. 异常原因分析
在多进程环境下，各进程独立进行日志写入。
当触发文件轮转条件（如时间或文件大小阈值）时，多个进程可能同时尝试执行文件重命名、新文件创建等操作，由此产生竞争条件，导致诸如文件不存在、权限冲突等异常情况。


2. 解决方案
2.1 使用队列来处理日志
借助日志队列，将所有进程的日志消息汇集到单个日志处理进程。如此一来，仅该进程负责实际的日志写入与文件轮转，规避了多进程竞争问题。

在此代码中，log_queue 队列负责收集各进程的日志记录，log_worker 进程从队列取出记录并写入日志文件，确保日志写入与轮转操作的唯一性，避免竞争。
"""

from fastapi import FastAPI
from logging.handlers import TimedRotatingFileHandler

import multiprocessing
import logging


app = FastAPI()


# log_queue = multiprocessing.Queue()
log_lock = multiprocessing.Lock()


def setup_logging():
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    file_handler = TimedRotatingFileHandler('app.log', when='midnight')
    file_handler.setFormatter(formatter)
    logger = logging.getLogger('app')
    logger.addHandler(file_handler)
    logger.setLevel(logging.INFO)
    return logger


def log_worker(queue):
    logger = setup_logging()
    while True:
        try:
            record = queue.get()
            if record is None:
                break
            logger.handlers(record)
        except Exception:
            import traceback
            print(traceback.format_exc())

log_process = multiprocessing.Process(target=log_worker, args=(log_queue,))
log_process.start()


def get_logger():
    logger = logging.getLogger('app')
    return logger


@app.get("/")
def read_root():
    logger = setup_logging()
    logger.info("Handling root request")
    # 假设这里需要手动触发轮转
    return {"Hello": "World"}


if __name__=="__main__":
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)